package apportioner

import (
	// "bp/cache"
	sqlc "bp/db/sqlc"
	"bp/internal/util"
)

// ItemAmountFactor 千分比(0-1000)
type ItemAmountFactor float64
type OffCompareKeyToOffTrialItemPtrMap map[OffCompareKey]*sqlc.OffTrialItem
type OffCompareKeyToItemAmountFactorMap map[OffCompareKey]ItemAmountFactor

func (s *ApportionerComServiceImp) genItemAmountDistribution(theMap OffCompareKeyToOffTrialItemPtrMap) (r OffCompareKeyToItemAmountFactorMap) {
	r = make(OffCompareKeyToItemAmountFactorMap)
	var sum int32
	for k := range theMap {
		sum += theMap[k].Cnt * theMap[k].ItemPrice
	}
	for k := range theMap {
		r[k] = ItemAmountFactor(util.RoundToPoint3(float64(theMap[k].Cnt*theMap[k].ItemPrice)/float64(sum)) * 1000)
	}
	return
}

func (s *ApportionerComServiceImp) genItemOffDistributionByUpsertOffApportionmentParamsPtrs(ptrs []*sqlc.UpsertOffApportionmentParams) (r OffCompareKeyToItemAmountFactorMap) {
	r = make(OffCompareKeyToItemAmountFactorMap)

	for _, ptr := range ptrs {
		k := s.ExtractOwnerUpsertOffApportionmentParamsKey()(ptr)
		if _, ok := r[k]; !ok {
			r[k] = 0
		}
		r[k] += ItemAmountFactor(ptr.Off)
	}

	return
}

// 查找原始金额最大的优惠试算项目
func (s *ApportionerComServiceImp) findOffTrialItemByMaxItemAmount(ptrs []*sqlc.OffTrialItem) (r *sqlc.OffTrialItem) {
	iv := util.Max(util.ToGenericSlice(ptrs), func(i1, i2 interface{}) util.Ord {
		v1, v2 := i1.(*sqlc.OffTrialItem), i2.(*sqlc.OffTrialItem)
		amount1, amount2 := v1.ItemPrice*v1.Cnt, v2.ItemPrice*v2.Cnt
		if amount1 < amount2 {
			return util.Lt
		} else if amount1 > amount2 {
			return util.Gt
		}
		return util.Eq
	})
	r = iv.(*sqlc.OffTrialItem)
	return
}

// 查找剩余金额最大的优惠交易明细
func (s *ApportionerComServiceImp) FindOffTransactionDetailByMaxRemainAmount(ptrs []*sqlc.OffTransactionDetail, mp OffCompareKeyToItemAmountFactorMap) (r *sqlc.OffTransactionDetail) {
	iv := util.Max(util.ToGenericSlice(ptrs), func(i1, i2 interface{}) util.Ord {
		v1, v2 := i1.(*sqlc.OffTransactionDetail), i2.(*sqlc.OffTransactionDetail)
		conv := s.ExtractOwnerOffTransactionDetailKey()
		k1, k2 := conv(v1), conv(v2)
		amount1, amount2 := v1.ItemPrice*v1.OutOrderDetailCnt, v2.ItemPrice*v2.OutOrderDetailCnt

		var off1, off2 ItemAmountFactor

		if v, ok := mp[k1]; ok {
			off1 = v
		}
		if v, ok := mp[k2]; ok {
			off2 = v
		}
		actual1, actual2 := ItemAmountFactor(amount1)-off1, ItemAmountFactor(amount2)-off2
		if actual1 < actual2 {
			return util.Lt
		} else if actual1 > actual2 {
			return util.Gt
		}
		return util.Eq
	})

	r = iv.(*sqlc.OffTransactionDetail)
	return
}
